package cn.le.io;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

/**
 * 在对于大文件进行操作时,性能问题一直是比较难处理,通过操作系统的内存映射文件支持,可以比较
 * 快速地对大文件进行操作,内存映射文件的原理在于把操作系统的内存地址映射到要操作的文件上,
 * 读取这些内存地址就相当于读取文件的内容,而改变这些内存地址的值就相当于改变文件中的内存,
 * 被映射到内存地址上的文件在使用上类似于操作系统中使用的虚拟内存文件,通过内存映射的方式对
 * 文件进行操作时,不再需要i/o操作完成,而是直接通过内存地址访问操作来完成,这就大大的提高了操作文件
 * 的性能,因为访问内存地址比i/o操作要快很多
 *
 * FileChannel类的map方法可以把一个文件的全部或者部分内存映射到内存中,所得到的是一个
 * ByteBuffer类的子类,mappedByteBUffer对象,程序只需要对这个MappedByteBuffer类
 * 的对象进行操作即可,对这个MappedByteBuffer类的对象所做的修改自动同步到文件内存中
 *
 *
 *内存映射时需要指定映射模式
 *  read_only:表示只能对映射之后的MappedByteBuffer类的对象进行读取操作
 *  read_write:表示可读可写的
 *  private:通过MappedButeBuffer类的对象所做的修改不会同步到文件中,而是被同步到一个私有的
 *  复本中,这些修改对其他同样映射了该文件的程序是不可以见的
 *
 */
public class MappedByteBufferDemo {

    public void test()
    {
        try (FileChannel channel = FileChannel.open(Paths.get("src.data"), StandardOpenOption.READ,StandardOpenOption.WRITE)) {
            MappedByteBuffer buffer =channel.map(FileChannel.MapMode.READ_WRITE, 0, channel.size());
            byte b = buffer.get(1024 * 1024);
            buffer.put(5 * 1024 * 1024, b);
            //将此缓冲区所做的内容更改强制写入包含映射文件的存储设备中。
            buffer.force();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws IOException {
        MappedByteBufferDemo.largeMappedFiles();
    }

    static int length = 0x8FFFFFF; //128MB
    public  static void largeMappedFiles() throws IOException {

        MappedByteBuffer out = new RandomAccessFile("F:\\date.txt","rw")
                .getChannel().map(FileChannel.MapMode.READ_WRITE,0,length);

        for (int i = length / 2; i < length/2+6 ; i++) {
            out.put((byte)'x');
        }
        for (int i = length / 2; i < length/2+6; i++) {
            System.out.println((char)out.get(i));
        }
    }

}
